//NOTE:      collect() ->    FromIterator 
//NOTE: diff in impl Trait for [V/&'a V /&'a mut V]

use std::fmt::{self, Debug,};
use std::mem;

struct MyVec<T> {
    vec: Vec<T>
}

impl<T> Default for MyVec<T> 
{
    fn default() -> Self {
        Self {
            vec:Vec::new(),
        }
    }
}

impl<T> MyVec<T> 
{
    fn new() -> Self {
        Self {
            vec: Vec::<T>::new()
        }
    }
    fn into_iter(self) -> IntoIter<T> {
        IntoIter {
            vec: RefCell::new(self.vec)
        }
    }
    fn len(&self) -> usize {
        self.vec.len()
    }

    fn push(&mut self, t: T) {
        self.vec.push(t)
    }

    fn iter(&self) -> Iter<'_, T> {
        Iter {
            source:self,
            index: 0,
        }
    }
    fn iter_mut(&mut self) -> IterMut<'_, T> {
        IterMut {
            source: self.vec.as_mut_slice(),
            index: 0,
        }
    }
    fn get(&self, index: usize) -> Option<&T>
    {
        self.vec.get(index)
    }
}


struct Iter<'a, T> {
    source: &'a MyVec<T>,
    index: usize
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.source.len()  {
            let r = self.source.get(self.index);
            self.index += 1;
            r
        } else {
            None
        }
    }
}

impl<'a> FromIterator<&'a String> for MyVec<String>{
    fn from_iter<I>(iter: I) -> Self 
    where 
        I: IntoIterator<Item=&'a String>,
    {
        let mut mv = MyVec::<String>::new();
        for i in iter { //because of I: IntoIterator
            mv.push(i.to_string())
        }
        mv
    }
}


struct IterMut<'a, T: 'a> {
    source: &'a mut [T],
    index: usize,
}

impl<'a, T: 'a> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item>
    {
        //TODO: write something for Splitting Borrows......
        //ref: Rustonomicon:  Chapter 3 ownshipt -> 3.11 splitting Borrows
        let slice = mem::take(&mut self.source);
        if slice.is_empty() { 
            None
        } else {
            let (l, r) = slice.split_at_mut(2);
            self.source = r;
            l.get_mut(0)
        }
    }
}


impl<'a> FromIterator<&'a mut String> for MyVec<String>{
    fn from_iter<I>(iter: I) -> Self 
    where 
        I: IntoIterator<Item=&'a mut String>,
    {
        let mut mv = MyVec::<String>::new();
        for i in iter { //because of I: IntoIterator
            mv.push(i.to_string())
        }
        mv
    }
}



impl<T> FromIterator<T> for MyVec<T>{

    fn from_iter<I>(iter: I) -> Self 
    where 
        I: IntoIterator<Item=T>,
    {
        let mut mv = MyVec::<T>::new();
        for i in iter { //because of I: IntoIterator
            mv.push(i)
        }
        mv
    }
}

use std::cell::RefCell;
struct IntoIter<T> {
    vec: RefCell<Vec<T>>
}

impl<T> IntoIter<T> {
    fn len(&self) -> usize {
        self.vec.borrow().len()
    }
}


impl<T> Iterator for IntoIter<T> 
{
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        self.vec.borrow_mut().pop()
    }

    fn collect<B>(self) -> B 
    where B: FromIterator<Self::Item>
    {
        FromIterator::from_iter(self)
    }

}

impl<T> Debug for MyVec<T> 
where T: Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.vec)
    }
}


trait TCall {
    fn call(&self) -> i64;
    fn call_mut(&mut self) -> i64;
    fn call_move(self) -> i64;
}

impl<T> TCall for MyVec<T> {
    fn call(&self) -> i64 {
        11_i64
    }
    fn call_mut(&mut self) -> i64 {
        21_i64
    }
    fn call_move(self) -> i64 {
        31_i64
    }
}

impl<'a, T> TCall for &'a MyVec<T> {
    fn call(&self) -> i64 {
        12_i64
    }
    fn call_mut(&mut self) -> i64 {
        22_i64
    }
    fn call_move(self) -> i64 {
        32_i64
    }
}
impl<'a, T> TCall for  &'a mut MyVec<T> {
    fn call(&self) -> i64 {
        13_i64
    }
    fn call_mut(&mut self) -> i64 {
        23_i64
    }
    fn call_move(self) -> i64 {
        33_i64
    }
}





#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn use_collect(){

        let mut v = MyVec::<String>::new();
        v.push("1".to_string());
        v.push("2".to_string());
        { //inot_iter().collect
        let m: MyVec<String> = v.into_iter().collect();
        println!("debug:{:?}", m);
        }

        {//iter().collect
            let mut v = MyVec::<String>::new();
            v.push("1".to_string());
            v.push("2".to_string());
            let m: MyVec<String> = v.iter().collect::<MyVec<String>>();
            println!("debug:{:?}", m);
        }
        /*
        { //iter_mut().collect TODO:
            let mut v = MyVec::<String>::new();
            v.push("1".to_string());
            v.push("2".to_string());
            let m: MyVec<String> = v.iter_mut().collect::<MyVec<String>>();
            println!("debug:{:?}", m);
        }*/
    }

    #[test]
    fn use_into_iter() {
        let mut v = vec![1, 2, 3, ];
        let _ = v.iter().collect::<Vec<_>>();
        println!("{:?}", v);
        let _ = v.iter_mut().collect::<Vec<_>>();
        println!("{:?}", v);
        let _ = v.into_iter().collect::<Vec<_>>();
        //println!("{:?}", v);//compile error
    }
    #[test]
    fn val_ref_mut_ref(){
        {
        let mut v = MyVec::<String>::new();
        assert_eq!(11, (&(v)).call());
        assert_eq!(12, (&(&v)).call());
        assert_eq!(13, (&(&mut v)).call());

        assert_eq!(21 ,(&mut (v)).call_mut());

        assert_eq!(22, (&mut (&v)).call_mut());
        assert_eq!(23, (&mut (&mut v)).call_mut());
        }

        {
        let v = MyVec::<String>::new();
        assert_eq!(31,(v).call_move());
        }
        {
        let v = MyVec::<String>::new();
        assert_eq!(32,(&v).call_move());
        }
        {
        let mut v = MyVec::<String>::new();
        assert_eq!(33,(&mut v).call_move());
        }
    }


}
